package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.util.FileUtil;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.base.BaseEntity;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.client.OrderInfoFeignClient;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
@SuppressWarnings({"unchecked", "rawtypes"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;
    @Autowired
    private AlbumStatMapper albumStatMapper;
    @Autowired
    FileUtil fileUtil;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    RBloomFilter rBloomFilter;


    /**
     * 保存新增专辑数据
     *
     * @param albumInfoVo
     */
    @Override
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {
        // 声明与表对应的DO
        AlbumInfo albumInfo = new AlbumInfo();
        // 将VO的属性复制到DO
        BeanUtils.copyProperties(albumInfoVo, albumInfo);

        // 补全其他属性
        albumInfo.setUserId(AuthContextHolder.getUserId());
        albumInfo.setStatus(SystemConstant.TRACK_STATUS_WAIT);
        // 新增专辑数据
        if (!save(albumInfo)) {
            // 新增失败抛异常
            throw new GuiguException(201, "专辑数据有误");
        }
        // 新增专辑标签数据 - AlbumAttributeValue
        Long albumId = albumInfo.getId();
        saveAlbumAttributeValueVo(albumId, albumInfoVo.getAlbumAttributeValueVoList());
        // 初始化专辑统计数据
        initAlbumStat(albumId);
        // 根据isOpen判断要不要存入ES：0不公开 1公开
        String isOpen = albumInfo.getIsOpen();
        if (isOpen.equals("1")) {
            // 将专辑数据写入es
            rabbitTemplate.convertAndSend("album_and_search_exchange"
                    , "album.upper"
                    , albumId + "");
        }
        // 将专辑存入布隆过滤器 --- 优化方案：rabbitmq异步操作
        rBloomFilter.add("getAlbumInfo:" + Arrays.asList(albumInfo.getId().toString()));
    }


    /**
     * 分页查询专辑数据方法实现
     *
     * @param page
     * @param albumInfoQuery
     * @return
     */
    @Override
    public Page<AlbumListVo> findAlbumInfoPage(Page<AlbumListVo> page,
                                               AlbumInfoQuery albumInfoQuery) {
        albumInfoQuery.setUserId(AuthContextHolder.getUserId());
        return albumInfoMapper.selectAlbumInfo(albumInfoQuery, page);
    }


    /**
     * 删除专辑
     *
     * @param albumId
     */
    @Override
    public void removeAlbumInfo(Long albumId) {
        // 验证验证当前用户下该id的专辑是否存在
        AlbumInfo albumInfo = getOne(new LambdaQueryWrapper<AlbumInfo>()
                .eq(AlbumInfo::getUserId, AuthContextHolder.getUserId())
                .eq(AlbumInfo::getId, albumId));
        if (albumInfo == null) {
            // 专辑不存在，抛异常
            throw new GuiguException(201, "专辑不存在");
        }
        // 删除专辑封面
        String coverUrl = albumInfo.getCoverUrl();
        fileUtil.deleteFile(coverUrl);
        // 删除专辑
        removeById(albumId);
        // 删除专辑绑定标签
        albumAttributeValueMapper.delete(
                new LambdaQueryWrapper<AlbumAttributeValue>()
                        .eq(AlbumAttributeValue::getAlbumId, albumId));
        // 删除专辑绑定统计数据
        albumStatMapper.delete(
                new LambdaQueryWrapper<AlbumStat>()
                        .eq(AlbumStat::getAlbumId, albumId));
        // 删除ES中的数据
        rabbitTemplate.convertAndSend("album_and_search_exchange"
                , "album.down"
                , albumId + "");
        // 删除Redis中的数据
        rabbitTemplate.convertAndSend("album_and_search_exchange"
                , "album.redis"
                , albumId + "");
    }


    /**
     * 根据用户修改专辑条件回显查询
     *
     * @param albumId
     * @return
     */
    @Override
    public Object getAlbumInfo(Long albumId) {
        // 查询当前用户下指定id的专辑并验证
        AlbumInfo albumInfo = getOne(new LambdaQueryWrapper<AlbumInfo>()
                .eq(AlbumInfo::getUserId, AuthContextHolder.getUserId())
                .eq(AlbumInfo::getId, albumId));
        if (albumInfo == null) {
            throw new GuiguException(201, "专辑不存在");
        }
        // 根据专辑id查询专辑标签数据
        List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(
                new LambdaQueryWrapper<AlbumAttributeValue>()
                        .eq(AlbumAttributeValue::getAlbumId, albumId));
        // 包装专辑标签
        albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);
        // 返回
        return albumInfo;
    }

    /**
     * 保存修改专辑数据
     *
     * @param albumId
     * @param albumInfoVo
     */
    @Override
    public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
        // 验证专辑信息
        AlbumInfo albumInfo = getOne(new LambdaQueryWrapper<AlbumInfo>()
                .eq(AlbumInfo::getUserId, AuthContextHolder.getUserId())
                .eq(AlbumInfo::getId, albumId));
        // 若专辑不存在，结束
        if (albumInfo == null) {
            throw new GuiguException(201, "专辑不存在");
        }
        // 属性转移
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        // 更新专辑数据
        updateById(albumInfo);
        // 根据专辑id删除原有标签
        albumAttributeValueMapper.delete(
                new LambdaQueryWrapper<AlbumAttributeValue>()
                        .eq(AlbumAttributeValue::getAlbumId, albumId));
        // 保存新标签
        saveAlbumAttributeValueVo(albumId, albumInfoVo.getAlbumAttributeValueVoList());
        String isOpen = albumInfoVo.getIsOpen();
        // 根据修改后isOpen的值判断
        if (isOpen.equals("0")) {
            // 下架，从es中删除
            rabbitTemplate.convertAndSend("album_and_search_exchange"
                    , "album.down"
                    , albumId + "");
            // 删除Redis中的数据
            rabbitTemplate.convertAndSend("album_and_search_exchange"
                    , "album.redis"
                    , albumId + "");
        } else {
            // 写入es
            rabbitTemplate.convertAndSend("album_and_search_exchange"
                    , "album.upper"
                    , albumId + "");
        }
    }


    /**
     * 查询专辑列用于声音添加
     *
     * @return
     */
    public List<AlbumInfo> findUserAllAlbumList() {
        // 查询当前登录用户的审核通过的未完结的专辑
        return page(new Page<>(1, 10), new LambdaQueryWrapper<AlbumInfo>()
                .eq(AlbumInfo::getUserId, AuthContextHolder.getUserId())
                .eq(AlbumInfo::getStatus, SystemConstant.ALBUM_STATUS_PASS)
                .eq(AlbumInfo::getIsFinished, 0)
                .orderByDesc(BaseEntity::getId)).getRecords();
    }


    /**
     * 获取专辑标签list
     *
     * @param albumId
     * @return
     */
    @Override
    public List<AlbumAttributeValue> getAlbumAttributeValueList(Long albumId) {
        return albumAttributeValueMapper.selectList(
                new LambdaQueryWrapper<AlbumAttributeValue>()
                        .eq(AlbumAttributeValue::getAlbumId, albumId));
    }


    /**
     * 获取专辑统计信息
     *
     * @param albumId
     * @return
     */
    @Override
    public Map<String, Object> getAlbumStatMap(Long albumId) {
        List<AlbumStat> albumStatList = albumStatMapper.selectList(
                new LambdaQueryWrapper<AlbumStat>()
                        .eq(AlbumStat::getAlbumId, albumId));
        return albumStatList.stream().collect(Collectors.toMap(
                albumStat -> albumStat.getStatType(),
                albumStat -> albumStat.getStatNum()
        ));
    }


    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public AlbumInfo getAlbumInfoFromDbOrRedis(Long albumId) {
        // 从Redis中查询  key = album:info:1
        AlbumInfo albumInfo =
                (AlbumInfo) redisTemplate.opsForValue().get(RedisConstant.ALBUM_INFO_PREFIX + albumId);
        if (albumInfo != null) {
            // redis有 返回给前端
            return albumInfo;
        }
        // 没有 查DB
        albumInfo = getById(albumId);
        if (albumInfo == null) {
            // DB无 初始化 存Redis 5分钟过期
            albumInfo = new AlbumInfo();
            redisTemplate.opsForValue().set(RedisConstant.ALBUM_INFO_PREFIX + albumId, albumInfo, 5, TimeUnit.MINUTES);
        } else {
            // DB有 存Redis 60分钟过期
            redisTemplate.opsForValue().set(RedisConstant.ALBUM_INFO_PREFIX + albumId, albumInfo, 60, TimeUnit.MINUTES);
        }
        return albumInfo;
    }


    /**
     * 专辑添加 - 保存专辑标签
     *
     * @param albumInfoId
     * @param albumAttributeValueVoList
     */
    private void saveAlbumAttributeValueVo(Long albumInfoId
            , List<AlbumAttributeValueVo> albumAttributeValueVoList) {
        // 遍历list将元素属性复制给do
        albumAttributeValueVoList.stream().forEach(albumAttributeValueVo -> {
            // 声明do
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            // 复制属性
            BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
            // 补全属性
            albumAttributeValue.setAlbumId(albumInfoId);
            // 保存
            int insertNum = albumAttributeValueMapper.insert(albumAttributeValue);
            // 校验保存结果
            if (insertNum <= 0) {
                throw new GuiguException(201, "新增专辑标签失败");
            }
        });

    }

    /**
     * 专辑添加 - 初始化专辑统计数据
     *
     * @param albumInfoId
     */
    private void initAlbumStat(Long albumInfoId) {
        // 声明
        AlbumStat albumStat = new AlbumStat();
        // 设置初始值
        albumStat.setStatNum(0);

        // 设置专辑id
        albumStat.setAlbumId(albumInfoId);
        // 指定播放量并初始化
        albumStat.setStatType(SystemConstant.ALBUM_STAT_PLAY);
        albumStatMapper.insert(albumStat);

        // 去除id 指定订阅量并初始化
        albumStat.setId(null);
        albumStat.setStatType(SystemConstant.ALBUM_STAT_SUBSCRIBE);
        albumStatMapper.insert(albumStat);

        // 去除id 指定购买量并初始化
        albumStat.setId(null);
        albumStat.setStatType(SystemConstant.ALBUM_STAT_BROWSE);
        albumStatMapper.insert(albumStat);

        // 去除id 指定评论连并初始化
        albumStat.setId(null);
        albumStat.setStatType(SystemConstant.ALBUM_STAT_COMMENT);
        albumStatMapper.insert(albumStat);
    }

    @Resource
    private OrderInfoFeignClient orderInfoFeignClient;
    @Autowired
    private TrackInfoMapper trackInfoMapper;

    /**
     * 付款后更新专辑/声音统计信息：购买次数
     * stat_type = '0403'
     * @param orderNo
     */
    @Override
    public void updateAlbumOrTrackStat(String orderNo) {
        // 查询订单详情
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderNo);
        // 判断订单类型 -- 声音 or 专辑
        String itemType = orderInfo.getItemType();
        // 付款项目类型: 1001-专辑 1002-声音 1003-vip会员
        if (itemType.equals("1001")){
            // 专辑订单
            Long albumId = orderInfo.getOrderDetailList().get(0).getItemId();
            albumStatMapper.updateAlbumStat(albumId,1);
        }else if (itemType.equals("1002")){  // 声音订单
            // 获取orderDetail
            List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
            // 获取交易笔数 -- 购买的声音的数量
            int num = orderDetailList.size();
            // 获取trackId
            Long trackId = orderDetailList.get(0).getItemId();
            // 获取声音实体
            TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
            // 获取albumId
            Long albumId = trackInfo.getAlbumId();
            // 更新专辑购买量
            albumStatMapper.updateAlbumStat(albumId,num);
        }
    }

}
